<template>
    <div class="ea-tabs ea-tabs-top w-full h-full flex flex-col" :class="Class">
        <div class="ea-tabs-header mb-2.5">
            <div class="ea-tabs-nav-warp w-full h-full relative">
                <div class="ea-tabs-nav-scroll flex relative">
                    <div
                        class="ea-tabs-active-bar absolute bottom-0 left-0 transition-all duration-200"
                        :style="itemStyle"
                    />
                    <div
                        v-for="(component, index) in slotsComponentProps"
                        :key="component.label"
                        :ref="(el) => setElMap(component.label, el)"
                        class="ea-tabs-item h-10 flex items-center font-semibold cursor-pointer"
                        :class="{ 'is-active': component.label === modelValue }"
                        @click="handle(component.label, index)"
                    >
                        {{ component.label }}
                    </div>
                </div>
            </div>
        </div>
        <div class="ea-tabs_content">
            <Transition name="slide-fade" mode="out-in">
                <div class="transition_div" :key="props.modelValue">
                    <slot></slot>
                </div>
            </Transition>
        </div>
    </div>
</template>

<script setup lang="ts">
import { computed, defineProps, nextTick, onMounted, provide, ref, useSlots, watch } from 'vue'
import type { ComponentPublicInstance } from 'vue'
const slots = useSlots()
const slotsComponentProps = ref<{ label: string; name: string }[]>([])
const itemStyle = ref<string>('width:0px;transform: translateX(0px);')
const elMap = ref(new Map<string, HTMLElement>())
interface Props {
    modelValue: string
    class?: string
}
const emit = defineEmits<{
    (e: 'update:modelValue', value: string): void
    (e: 'click', value: string): void
}>()
const props = defineProps<Props>()

const handle = (label: string, index: number) => {
    emit('update:modelValue', label)
    emit('click', label)
    itmeStyleConverter(label, index)
}
const setElMap = (label: string, el: Element | ComponentPublicInstance | null) => {
    if (el) {
        elMap.value.set(label, el as HTMLElement)
    }
}

const initFirstItem = () => {
    itmeStyleConverter(slotsComponentProps.value[0].label, 0)
}
const itmeStyleConverter = (label: string, index?: number) => {
    const el = elMap.value.get(label)
    if (!el) return `width:0px;transform: translateX(0px);`
    if (el instanceof HTMLElement) {
        let width = el.clientWidth

        // 计算前几个元素的总宽度作为偏移量
        let offsetX = 0
        for (let i = 0; i < index!; i++) {
            const prevLabel = slotsComponentProps.value[i]?.label
            if (prevLabel) {
                const prevEl = elMap.value.get(prevLabel)
                if (prevEl instanceof HTMLElement) {
                    offsetX += prevEl.clientWidth
                }
            }
        }
        if (elMap.value.size - 1 === index) {
            width = width - 13
            offsetX = offsetX + 13
        } else if (index === 0) {
            width = width - 13
        } else {
            width = width - 23
            offsetX = offsetX + 13
        }

        itemStyle.value = `width:${width}px;transform: translateX(${offsetX}px);`
    } else {
        console.log('el is not an HTMLElement:', el)
    }
}

const getSlotComponentProps = () => {
    if (!slots.default) return
    const defaultSlots = slots.default()
    defaultSlots.forEach((item) => {
        if (item.props && item.props.label && item.props.name) {
            slotsComponentProps.value.push(item.props as { label: string; name: string })
        }
    })
}

const Class = computed(() => props.class)

const activeName = ref<string>(props.modelValue)
watch(
    () => props.modelValue,
    (newVal) => {
        activeName.value = newVal
    },
)

provide('activeName', activeName)

onMounted(() => {
    nextTick(() => {
        initFirstItem()
    })
    getSlotComponentProps()
})
</script>

<style lang="scss" scoped></style>
